除了middleware可以對原本request/response加工之外,nest.js提供interceptor可以對於程式要進入method之前與之後,執行一段程式或是對輸入輸出訊息做處理,稱之Aspect-Oriented Programming(AOP)
Interceptor必須實作NestInterceptor介面
interceptor方法傳入兩個引數ExecutionContext
以改變reponse內容為例,把原本的response內容再添加額外資訊
新增transformRes.interceoptor.ts
import { ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class TransformResInterceptor implements NestInterceptor { // 實作NestInterceptor介面
intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> {
const controller = context.getClass().name; // 取得controller name
const handler = context.getHandler().name; // 取得method name
return call$.pipe(
map(data => // 原response內容
({ // 改變response內容
controller,
handler,
data,
})),
);
}
}
在app.module.ts註冊interceptor
...
@Module({
imports: [SharedModule],
controllers: [AppController],
providers: [
AppService,
AuthGuard,
HttpExceptionFilter,
TransformResInterceptor,
],
})
export class AppModule implements NestModule{
...
用@UseInterceptors套用TransformResInterceptor
app.controller.ts
...
@Controller()
@UseFilters(HttpExceptionFilter)
@UseGuards(AuthGuard)
@UseInterceptors(TransformResInterceptor)
export class AppController {
redisClient: redis.RedisClient;
constructor(private appService: AppService){
// this.redisClient = redis.createClient(6379, 'redis-server');
// this.redisClient.set('counter', '0');
}
@Get()
sayHello(){
return this.appService.sayHello();
}
@Post()
@UsePipes(UserDTOValidationPipe)
@ReflectMetadata('roles', ['admin', 'superuser'])
create(@Body() userDTO: UserDTO){
//throw new HttpException('糟糕!您的要求有問題,請洽系統管理員', HttpStatus.BAD_REQUEST);
return `使用者:${userDTO.username}已建立`;
}
...
使用postman測試